Skip to main content

Full text of "Scenix-SXC Code Development System OCR"

See other formats


Page 1 of 5 



*********************************************************** 
Virtual Peripheral UART 



Length: 67 bytes (total) 

Authors: Chip Gracey, President, Parallax Inc. 

modified by Craig Webb, Consultant to Scenix Semiconductor, Inc. 
Written: 97/03/10 to 98/7/09 

****************************************************************************** 

****** Assembler directives 

uses: SX28AC, 2 pages of program memory, 8 banks of RAM, high speed osc. 
operating in turbo mode, with 8 -level stack & extended option reg. 

DEVICE pins2 8 , pages 2 , banks 8 , oschs 

DEVICE turbo, stackx, optionx 

ID 'UART' ,-program ID label 

RESET reset_entry ;set reset/boot address 

******************************* p 17051*3.1x1 Vs.!* i 3.b lss *************************** 



Port Assignment: Bit variables 



rxjin 
tx_pin 



EQU 
EQU 



ra . 2 
ra. 3 



****** Register definitions (bank 0) 



org 



mam 



; UART receive input 
; UART transmit output 



; start of program registers 
;main bank 



temp ds 1 

byte ds 1 

flags DS 1 

number_low ds 1 

number_high ds 1 

hex ds 1 

string ds 1 



,-temporary storage 
/temporary UART / 1 2 C shift reg. 
/program flags register 
; low byte of rec ' d value 
/high byte of ree'd value 
/value of ree'd hex number 
/indirect ptr to output string 



rx_f lag 



EQU 



flags . 5 



/signals when byte is received 



serial 



org 



lOh 
$ 



,-bank3 variables 
/UART bank 



tx_high 

tx_low 

tx_count 

tx_divide 

rx_count 

rx_divide 

rx_byte 



ds 
ds 
ds 
ds 
ds 
ds 
ds 



1 
1 
1 
1 
1 
1 
1 



hi byte to transmit 
low byte to transmit 
number of bits sent 
xmit timing (/16) counter 
number of bits received 
receive timing counter 
buffer for incoming byte 



The following three values determine the UART baud rate. 
The value of baud_bit and int_period affect the baud rate as follows: 
Baud rate = 50MHz/ (2^baud_bit * int_period * RTCC_prescaler ) 



ftp ://ftp . scenix . com/ vps/uart_vp . sre 



9/1/1999 



Page 2 of 5 



Note: 1 =< baud_bit =< 7 

*int_period must <256 and longer than the length of the slowest 
possible interrupt sequence in instruction cycles. 
Changing the value of int_period will affect the 
rest of the virtual peripherals due to timing issues. 
The start delay value must be set equal to (2 A baud_bit) *1 . 5 + 1 

*** 2400 baud (for slower baud rates, increase the RTCC prescaler) 



baud_bit 

start_delay 

int_period 

*** 9600 baud 
baud_bit = 
start_delay 
int_period 

*** 19200 baud 
baud_bit 
start_delay 
int_period 

*** 3 8400 baud 
baud_bit 
start_delay 
int_period 

*** 57600 baud 
baud_bit 
start_delay 
int_period 

*** 115.2k baud 
baud_bit 
start_delay 
int_period 



128+64+1 
163 



16+8+1 
163 



4 

16+8+1 
163 



3 

8 + 4 + 1 
163 



2 

4+2 + 1 
217 



1 

2 + 1 + 1 
217 



for 2400 baud 



for 9600 baud 



for 19200 baud 



for 38400 baud 



for 57600 baud 



;for 115. 2K baud 



23 0.4k baud (for faster rates, reduce int_period - see above*) 



baud_bit 

start_delay 

int_period 





1 + + 
217 



**************************** INTERRUPT C 



for 230 .4K baud 



******************************* 



Note: The interrupt code must always originate at Oh. 

Care should be taken to see that any very timing sensitive routines 
(such as adcs, etc.) are placed before other peripherals or code 
which may have varying execution rates (like the UART, for example) 



interrupt 



ORG 



/interrupt starts at Oh 



**** virtual Peripheral: Universal Asynchronous Receiver Transmitter (UART) 

This routine sends and receives RS232C serial data, and is currently 
configured (though modifications can be made) for the popular 
"No parity-checking, 8 data bit, 1 stop bit" (N,8,l) data format. 
RECEIVING: The rx_flag is set high whenever a valid byte of data has been 
received and it the calling routine's responsibility to reset this flag 
once the incoming data has been collected. 



ftp : // ftp . scenix . com/vp s/uart_vp . src 



9/1/1999 



14*- 



Q\OOO01O 



Page 3 of 5 



TRANSMITTING: The transmit routine requires the data to be inverted 
and loaded (tx_high+tx_low) register pair (with the inverted 8 data bits 
stored in tx_high and tx_low bit 7 set high to act as a start bit) . Then 
the number of bits ready for transmission (10=1 start + 8 data + 1 stop) 
must be loaded into the tx_count register. As soon as this latter is done, 
the transmit routine immediately begins sending the data. 

This routine has a varying execution rate and therefore should always be 
placed after any timing-critical virtual peripherals such as timers, 
adcs, pwms , etc. 

Note : The transmit and receive routines are independent and either may be 
removed, if not needed, to reduce execution time and memory usage, 
as long as the initial "BANK serial" (common) instruction is kept. 



Input variable (s) 
Output variable (s 
Variable (s) affec 
Flag(s) affected 
Size : Transmit 
Receive 
Timing (turbo) : 
Transmit 



tx_low (only high bit used) , tx_high, tx_count 
rx_flag, rx_byte 
ted : tx_divide, rx_divide, rx_count 
rx_f 1 ag 

15 bytes + 1 byte shared with receive code 
20 bytes + 1 byte shared with transmit code 



Receive - 



bank 



(a) [not sending] 9 cycles 

(b) [sending] 19 cycles 

+ 1 cycle shared with RX code ("bank" instr.) 

(a) [not receiving] 9 cycles 

(b) [start receiving] 16 cycles 

(c) [receiving, awaiting bit] 13 cycles 

(d) [receiving, bit ready] 17 cycles 



serial ; switch to serial register bank 



: transmit 



: receive 



: rxbit 



clrb 

inc 

STZ 

SNB 

test 

JZ 

clc 

rr 

rr 

dec 

movb 

movb 

test 

j nz 

mov 

sc 

mov 

mov 

djnz 

setb 

dec 

sz 

rr 

snz 

setb 



tx_divide . baud_bit 
tx_divide 

tx_divide . baud_bit 
tx_count 
: receive 

tx_high 

tx_low 

tx_count 

tx_pin, /tx_low. 6 

c , rx_pin 
rx_count 
: rxbit 
w,#9 

rx_count , w 

rx_divide, #start_delay 
rx_divide, : rxdone 
rx_divide . baud_bit 
rx_count 

rx_byte 

rx_f lag 



clear xmit timing count flag 
only execute the transmit routine 
set zero flag for test 

every 2*baud_bit interrupt 
are we sending? 
if not, go to : receive 
yes, ready stop bit 

and shift to next bit 

decrement bit counter 
output next bit 

get current rx bit 
currently receiving byte? 
if so, jump ahead 
in case start, ready 9 bits 
skip ahead if not start bit 
it is, so renew bit count 
ready 1.5 bit periods 
middle of next bit? 
yes, ready 1 bit period 
last bit? 
if not 

then save bit 
if so 

then set flag 



: rxdone 



Q[O0C | OCJ 



mov 



w, #-int_period 



' ~~ 00/10(0© 
ftp://ftp.scenix.com/vps/uart_vp.src 00 lo 



/interrupt every 'int_period' clock 



9/1/1999 



Page 4 of 5 



: end_int 


retiw 




; ****** Enc j f 


interrupt sequence 


. ***************************** PROGRAM DATA 


; String data 


for user 


interface (must be in 


_hello 


dw 


13, 10, 13, 10, ' SX 2400 


_cr 


dw 


13 , 10, 


_prompt 


dw 


13 , 10, 1 > 1 , 


error 


dw 


'Error! ' , 13, 10, 


hex 


dw 


1 0123456789ABCDEF' 


_space 


dw 


1 ' ,0 


_s ample 


dw 


13,10, 1 Sample= 1 , 


view 


dw 


13 , 10 , 'Bytes stored: 



;exit interrupt 



***************************** SUBROUTINES ********************************* 
Subroutine - Get byte via serial port 
get_byte 



jnb rx_f lag, $ 

clrb rx_flag 
mov byte , rx_byte 



; Subroutine - Send byte via serial port 
send_byte bank serial 



,-wait till byte is received 
; reset the receive flag 
/store byte (copy using W) 
; & fall through to echo char back 



: wait 



test 
jnz 

not 

mov 

setb 

mov 

RETP 



tx_count 
: wait 



tx_high, w 

tx_low. 7 

tx count, #10 



;wait for not busy 



; ready bits (inverse logic) 

; store data byte 

; set up start bit 

;1 start + 8 data + 1 stop bit 

; leave and fix page bits 



; Subroutine - Send string pointed to by address in W register 



send_string mov 
: loop 



string, w 
mov w, string 

mov m,#0 
iread 
mov 



test 

snz 

RETP 

call 

inc 

jmp 



m,#$F 
w 



send_byte 
string 
: loop 



; store string address 

; read next string character 

with indirect addressing 
using the mode register 
reset the mode register 
are we at the last char? 
if not=0, skip ahead 
;yes, leave & fix page bits 
,-not 0, so send character 
; point to next character 
; loop until done 



***************************** MAIN PROGRAM CODE ****************************** 
ORG lOOh 



ftp : // ftp . scenix. com/ vp s/ uart_vp . src 



9/1/1999 



Page 5 of 5 



; Program execution begins here on power-up or after a reset 
/ 

reset_entry 



mov 


ra, #%1011 


/initialize port RA 


mov 


! ra, #%0100 


;Set RA in/out directions 


CLR 


FSR 


; reset all ram starting at 08h 


: zero_ram SB 


FSR . 4 


,-are we on low half of bank? 


SETB 


FSR . 3 


; If so, don't touch regs 0-7 


CLR 


IND 


; clear using indirect addressing 


IJNZ 


FSR, : zero_ram 


; repeat until done 


mov 


! option, #%10011111 


; enable rtcc interrupt 


; Main Program Loop 






mov 


w,# hello 


,-send hello string 


page 


send string 




call 


send_string 




mov 


w,# prompt 


; send prompt 


page 


send_string 




call 


send_string 




: loop call 


get byte 


;get byte via UART 


; <program code goes 


here> 




JMP 


: loop 


;back to main loop 


. *************** 
> 






END 




/End of program code 



ftp : // ftp . scenix . com/vp s/uart_vp . src 



9/1/1999